package com.xlserver.service;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.xlserver.dao.*;
import com.xlserver.domain.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.RequestParam;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.io.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Service
public class ScheduleService {
    @Autowired
    CounselorMapper counselorMapper;
    @Autowired
    SupervisorMapper supervisorMapper;
    @Autowired
    ScheduleAdjustMapper scheduleAdjust;
    @Autowired
    SupervisorBandCounselorMapper supervisorBandCounselorMapper;
    @Autowired
    ConsultationMapper consultationMapper;
    @Autowired
    StateMapper stateMapper;
    @Autowired
    MessageMapper messageMapper;
    @Autowired
    UserMapper userMapper;

    public JSONObject getCounselorMonthSchedule(int counselorId, int year, int month) {
        String weekSchedule = counselorMapper.selectById(counselorId).getSchedule();
        if(weekSchedule.length() == 1){
            weekSchedule = "0000000";
            counselorMapper.update(null,new UpdateWrapper<Counselor>().eq("cid",counselorId).set("cSchedule",weekSchedule));
        }
        String monthSchedule = "";
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, year);
        cal.set(Calendar.MONTH, month - 1);
        cal.set(Calendar.DAY_OF_MONTH, 1);
        int week1day = cal.get(Calendar.DAY_OF_WEEK) - 1;
        List<ScheduleAdjust> scheduleAdjustList = scheduleAdjust.selectList(new QueryWrapper<ScheduleAdjust>().eq("id",counselorId));
        //System.out.println(variableDate);
        int type;
        for (int i = 0; i < cal.getActualMaximum(Calendar.DAY_OF_MONTH); i++) {
            //ScheduleAdjust scheduleAdjustOneDay = scheduleAdjust.selectOne(new QueryWrapper<ScheduleAdjust>().eq("id",counselorId).eq("adjustTime",variableDate));
            if(scheduleAdjustList == null || scheduleAdjustList.isEmpty()){
                monthSchedule = monthSchedule + String.valueOf(weekSchedule.charAt((i + week1day-1) % 7));
                continue;
            }
            for(int j = 0; j<scheduleAdjustList.size(); j++){
                if(scheduleAdjustList.get(j).getAdjustTime().getDate() == i+1
                        && scheduleAdjustList.get(j).getAdjustTime().getMonth()+1 == month
                        && scheduleAdjustList.get(j).getAdjustTime().getYear()+1900 == year){
                    type = scheduleAdjustList.get(j).getAdjustType();
                    if (type == 1) {
                        monthSchedule = monthSchedule + "1";

                    }
                    else if (type == -1) {
                        monthSchedule = monthSchedule + "0";
                    }
                    else {
                        monthSchedule = monthSchedule + String.valueOf(weekSchedule.charAt((i + week1day -1) % 7));
                    }
                }
                else if(j==scheduleAdjustList.size()-1){
                    monthSchedule = monthSchedule + String.valueOf(weekSchedule.charAt((i + week1day -1) % 7));
                }
            }
        }
        JSONObject ret = new JSONObject();
        ret.put("monthSchedule", monthSchedule);
        return ret;
    } //done

    public JSONObject getCounselorWeekSchedule(int couselorId, Date date) {
        int year, month, day;
        year = date.getYear() + 1900;
        month = date.getMonth() + 1;
        day = date.getDate();
        //String monthSchedule = getCounselorMonthSchedule(couselorId,year,month).get("monthSchedule").toString();
        //System.out.println(monthSchedule);
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, year);
        cal.set(Calendar.MONTH, month - 1);
        cal.set(Calendar.DAY_OF_MONTH, day);
        int weekIndex = cal.get(Calendar.DAY_OF_WEEK);
        weekIndex--;
        if (weekIndex == 0) {
            weekIndex = 7;
        }
        //weekIndex 表示今天周几，1就表示星期一，7就表示星期天
        String result = "";
        String lastMonthSchedule = getCounselorMonthSchedule(couselorId, year, month - 1).get("monthSchedule").toString();
        String thisMonthSchedule = getCounselorMonthSchedule(couselorId, year, month).get("monthSchedule").toString();
        //获取日期为月底，本周星期日在下一个月，例如当天是1月31日，但是是星期六
        if (cal.getActualMaximum(Calendar.DAY_OF_MONTH) < day + 7 - weekIndex) {
            result = thisMonthSchedule.substring(day - weekIndex);
            result = result + getCounselorMonthSchedule(couselorId, year, month + 1).get("monthSchedule").toString().substring(0, 7 - weekIndex);
        }
        //获取日期为月初，例如当天是3月1日，但是是星期三，因此需要上一月的2天排班和这一月的5天排班
        else if (day < weekIndex) {
            result = lastMonthSchedule.substring(lastMonthSchedule.length() - weekIndex + day)
                    + thisMonthSchedule.substring(0, 7 - weekIndex + day);
        }
        //获取日期任意，如
        // 3月22日，当月剩下天数 >= 7天
        // 1月31日，但是当天是周日
        // 1月1日，但是当天是周一
        // 1月8日，当月已经过去时间 >= 7天
        else {
            result = result + thisMonthSchedule.substring(day - weekIndex, day + 7 - weekIndex);
        }
        JSONObject ret = new JSONObject();
        ret.put("counselorWeekSchedule", result);
        return ret;
    }            //done

    public JSONObject getTodayCounselor(Date d) {
        int year, month, day;
        year = d.getYear() + 1900;
        month = d.getMonth() + 1;
        day = d.getDate();
        Calendar cal = Calendar.getInstance();
        cal.set(year - 1, month - 1, day);
        List<Counselor> counselorToday = new ArrayList<>();
        List<Counselor> counselorList = counselorMapper.selectList(new QueryWrapper<>());
        for(int i=0;i<counselorList.size();i++){
            if(getCounselorMonthSchedule(counselorList.get(i).getCid(),year,month).get("monthSchedule").toString().charAt(day-1) == '1'){
                counselorToday.add(counselorList.get(i));
            }
        }
        JSONObject ret = new JSONObject();
        ret.put("counselorTodayInfo", counselorToday);
        return ret;
    }                                     //done

    public JSONObject getSupervisorMonthSchedule(int supervisorId, int year, int month) {
        String weekSchedule = supervisorMapper.selectById(supervisorId).getSchedule();
        if(weekSchedule.length() == 1){
            weekSchedule = "0000000";
            supervisorMapper.update(null,new UpdateWrapper<Supervisor>().eq("sid",supervisorId).set("sSchedule",weekSchedule));
        }
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, year);
        cal.set(Calendar.MONTH, month - 1);
        cal.set(Calendar.DAY_OF_MONTH, 1);
        int week1day = cal.get(Calendar.DAY_OF_WEEK) - 1;
        String monthSchedule = "";
        List<ScheduleAdjust> scheduleAdjustList = scheduleAdjust.selectList(new QueryWrapper<ScheduleAdjust>().eq("id",supervisorId));
        //System.out.println(variableDate);
        int type;
        for (int i = 0; i < cal.getActualMaximum(Calendar.DAY_OF_MONTH); i++) {
            //ScheduleAdjust scheduleAdjustOneDay = scheduleAdjust.selectOne(new QueryWrapper<ScheduleAdjust>().eq("id",counselorId).eq("adjustTime",variableDate));
            if(scheduleAdjustList == null || scheduleAdjustList.isEmpty()){
                monthSchedule = monthSchedule + String.valueOf(weekSchedule.charAt((i + week1day -1) % 7));
                continue;
            }
            for(int j = 0; j<scheduleAdjustList.size(); j++){
                if(scheduleAdjustList.get(j).getAdjustTime().getDate() == i + 1
                        && scheduleAdjustList.get(j).getAdjustTime().getMonth()+1 == month
                        && scheduleAdjustList.get(j).getAdjustTime().getYear()+1900 == year){
                    type = scheduleAdjustList.get(j).getAdjustType();
                    if (type == 1) {
                        monthSchedule = monthSchedule + "1";

                    }
                    else if (type == -1) {
                        monthSchedule = monthSchedule + "0";
                    }
                    else {
                        monthSchedule = monthSchedule + String.valueOf(weekSchedule.charAt((i + week1day-1) % 7));
                    }
                }
                else if(j==scheduleAdjustList.size()-1){
                    monthSchedule = monthSchedule + String.valueOf(weekSchedule.charAt((i + week1day-1) % 7));
                }
            }
        }
        JSONObject ret = new JSONObject();
        ret.put("monthSchedule", monthSchedule);
        return ret;
    } //done

    public JSONObject getSupervisorWeekSchedule(int supervisorId, Date date) {
        int year, month, day;
        year = date.getYear() + 1900;
        month = date.getMonth() + 1;
        day = date.getDate();
        String monthSchedule = getSupervisorMonthSchedule(supervisorId, year, month).get("monthSchedule").toString();
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, year);
        cal.set(Calendar.MONTH, month - 1);
        cal.set(Calendar.DAY_OF_MONTH, day);
        int weekIndex = cal.get(Calendar.DAY_OF_WEEK);
        weekIndex--;
        if (weekIndex == 0) {
            weekIndex = 7;
        }
        String result = "";
        if (cal.getActualMaximum(Calendar.DAY_OF_MONTH) < day + 7) {
            result = monthSchedule.substring(day - weekIndex);
            result = result + getSupervisorMonthSchedule(supervisorId, year, month + 1).get("monthSchedule").toString().substring(0, 7 - weekIndex);
        } else {
            result = monthSchedule.substring(day - 1, day + 7);
        }
        JSONObject ret = new JSONObject();
        ret.put("supervisorWeekSchedule", result);
        return ret;
    }         //done

    public JSONObject getTodaySupervisor(Date date) {
        int year, month, day;
        year = date.getYear() + 1900;
        month = date.getMonth() + 1;
        day = date.getDate();
        Calendar cal = Calendar.getInstance();
        cal.set(year - 1, month - 1, day);
        List<Supervisor> supervisorToday = new ArrayList<>();
        List<Supervisor> supervisorList = supervisorMapper.selectList(new QueryWrapper<>());
        for(int i=0;i<supervisorList.size();i++){
            if(getSupervisorMonthSchedule(supervisorList.get(i).getSid(),year,month).get("monthSchedule").toString().charAt(day-1) == '1'){
                supervisorToday.add(supervisorList.get(i));
            }
        }
        JSONObject ret = new JSONObject();
        ret.put("supervisorTodayInfo", supervisorToday);
        return ret;
    }

    public JSONObject adjustMonthSchedule(Date date, int id, int operation) {
        int maxId = scheduleAdjust.selectMaxId();
        List<ScheduleAdjust> adjustList = scheduleAdjust.selectList(new QueryWrapper<ScheduleAdjust>().eq("adjustTime",date).eq("id",id));
        ScheduleAdjust s = new ScheduleAdjust(maxId+1, operation, date, id);
        JSONObject ret = new JSONObject();
        if(adjustList.isEmpty()){
            scheduleAdjust.insert(s);
            ret.put("result", "success!");
        }
        else if(adjustList.size() == 1){
            if(adjustList.get(0).getAdjustType() + operation == 0){
                scheduleAdjust.delete(new QueryWrapper<ScheduleAdjust>().eq("adjustTime",date).eq("id",id));
                scheduleAdjust.insert(s);
                ret.put("result", "success! New adjustment is applied!");
            }
            else{
                ret.put("result","error! Adjustment has already been inserted!");
            }
        }
        else{
            ret.put("error","multiple adjust records detected!");
        }
        return ret;
    }

    public JSONObject getPersonTodayStatus(int id) {
        JSONObject ret = new JSONObject();
        ret.put("todayStatus",stateMapper.selectById(id).getState());
        return ret;
    }

    public JSONObject getTodayCounselorWithBand(Date d, int sid) {
        List<Counselor> counselors = JSON.parseArray(getTodayCounselor(d).getStr("counselorTodayInfo"), Counselor.class);
        getTodayCounselor(d).get("counselorTodayInfo");
        Counselor counselor = new Counselor();
        List<Counselor> bandCounselors = supervisorBandCounselorMapper.selectAllBand(sid);
        for (int i = 0; i < counselors.size(); i++) {
            counselor = counselors.get(i);
            if (!bandCounselors.contains(counselor))
                counselors.remove(i);
        }
        JSONObject ret = new JSONObject();
        ret.put("bandOnlineCounselor", counselors);
        return ret;
    }

    public JSONObject getPersonTodayWeekSchedule(Date date, int id) {
        if (id > 30000) {
            return getSupervisorWeekSchedule(id, date);
        }
        return getCounselorWeekSchedule(id, date);
    }

    public JSONArray getMonthSchedule(Date date) {
        int year,month;
        year = date.getYear() + 1900;
        month = date.getMonth() + 1;
        JSONObject ret;
        JSONArray jsonArray = new JSONArray();
        JSONArray dayCounselor, daySupervisor;
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, month - 1);
        List<Counselor> counselorList;
        List<Supervisor> supervisorList;
        Counselor counselor = new Counselor();
        Supervisor supervisor = new Supervisor();
        JSONObject singleCounselor;
        JSONObject singleSupervisor;
        for (int i = 0; i < calendar.getActualMaximum(Calendar.DAY_OF_MONTH); i++) {
            ret = new JSONObject();
            date.setDate(i+1);
            counselorList = JSON.parseArray(getTodayCounselor(date).getStr("counselorTodayInfo"),Counselor.class);
            supervisorList = JSON.parseArray(getTodaySupervisor(date).getStr("supervisorTodayInfo"),Supervisor.class);
            dayCounselor = new JSONArray();
            daySupervisor = new JSONArray();
            for (int j = 0; j < counselorList.size(); j++) {
                singleCounselor = new JSONObject();
                counselor = (Counselor) counselorList.get(j);
                singleCounselor.put("id", counselor.getCid());
                singleCounselor.put("name", counselor.getName());
                dayCounselor.add(singleCounselor);
            }
            for (int j = 0; j < supervisorList.size(); j++) {
                singleSupervisor = new JSONObject();
                supervisor = (Supervisor) supervisorList.get(j);
                singleSupervisor.put("id", supervisor.getSid());
                singleSupervisor.put("name", supervisor.getName());
                daySupervisor.add(singleSupervisor);
            }
            ret.put("year", date.getYear()+1900);
            ret.put("month", date.getMonth()+1);
            ret.put("day", date.getDate());
            ret.put("counselors", dayCounselor);
            ret.put("supervisors", daySupervisor);
            jsonArray.add(ret);
        }
        return jsonArray;
    }

    public JSONArray getTodayCounselorDetails(Date date,int uid){
        JSONArray ret = new JSONArray();
        JSONObject res;
        List <Counselor> counselorList = JSON.parseArray(getTodayCounselor(date).getStr("counselorTodayInfo"),Counselor.class);
        int tempSid;
        for(int i=0;i<counselorList.size();i++){
            res = new JSONObject();
            tempSid = counselorList.get(i).getCid();
            res.put("Counselor",counselorList.get(i));
            if(consultationMapper.selectList(new QueryWrapper<Consultation>().eq("uid",uid).eq("cid",tempSid)).isEmpty()){
                res.put("consultedBefore",0);
            }
            else {
                res.put("consultedBefore",1);
            }
            res.put("counselorState",stateMapper.selectById(counselorList.get(i).getCid()));
            ret.add(res);
        }
        return ret;
    }
    public void exportMultipleConsultationHistory(int uid){

    }
    public String getNameFromId(int id){
        String str;
        if(id < 20000){
            str = userMapper.selectById(id).getUsername();
        }
        else if(id < 30000){
            str = counselorMapper.selectById(id).getName();
        }
        else{
            str = supervisorMapper.selectById(id).getName();
        }
        return str;
    }
    public String exportSingleHistory(int hid) throws IOException {
        int uid = consultationMapper.selectById(hid).getUid();
        int cid = consultationMapper.selectById(hid).getCid();
        String uname = userMapper.selectById(uid).getUsername();
        String cname = counselorMapper.selectById(cid).getName();
        String path = hid + "-" + uname + "-" + cname + "-" + ".txt";
        File result = new File(path);
        if(!result.exists()){
            result.createNewFile();
        }
        FileWriter fw;
        fw = new FileWriter(result.getAbsoluteFile());
        BufferedWriter bw;
        bw = new BufferedWriter(fw);
        String content;
        content = "访客姓名：" + uname + " " + "咨询师姓名：" + cname +
                " " + "开始时间：" + consultationMapper.selectById(hid).getBeginTime() +
                " " + "结束时间：" + consultationMapper.selectById(hid).getEndTime();
        bw.write(content);
        bw.newLine();
        String senderName,receiverName;
        List<Message> messageList = new ArrayList<>();
        messageList = messageMapper.selectList(new QueryWrapper<Message>().eq("hid",hid));
        for(int i=0 ; i<messageList.size() ; i++){
            if(messageList.get(i).getSenderId() == uid){
                senderName = uname;
                receiverName = cname;
            }
            else{
                senderName = cname;
                receiverName = uname;
            }
            content = "发送者：" + senderName + " " + messageList.get(i).getTime() + " " + messageList.get(i).getMsg();
            bw.write(content);
            bw.newLine();
        }
        bw.close();
        return path;
    }
    public String exportConsultationHistory(int userid) throws IOException {
        List<Message> messageList = new ArrayList<>();
        List<Consultation> consultationList = consultationMapper.selectList(new QueryWrapper<Consultation>().eq("uid",userid));
        if(consultationList.size() == 0){
            return null;
        }
        if(consultationList.size() == 1){
            return exportSingleHistory(consultationList.get(0).getHid());
        }
        String[] path = new String[consultationList.size()];
        String uname = userMapper.selectById(userid).getUsername();
        File zip = new File(uname+".zip");
        if(!zip.exists()){
            zip.createNewFile();
        }
        FileInputStream fis = null;
        ZipOutputStream zos = null;
        FileOutputStream fos = null;
        try{
            fos = new FileOutputStream(zip);
            zos = new ZipOutputStream(fos);
            ZipEntry zipEntry = null;
            File file;
            for(int i=0; i<consultationList.size(); i++){
                file = new File(exportSingleHistory(consultationList.get(i).getHid()));
                fis = new FileInputStream(file);
                zipEntry = new ZipEntry(file.getName());
                zos.putNextEntry(zipEntry);
                int len;
                byte[] buffer = new byte[1024];
                while((len = fis.read(buffer)) > 0){
                    zos.write(buffer,0,len);
                }
            }
            zos.closeEntry();
            zos.close();
            fis.close();
            fos.close();
        }catch (Exception e){
            e.printStackTrace();
        }
        return uname+".zip";
    }
    public void pushConsultationHistory(HttpServletResponse response,int uid){

    }
}

